import { Injectable } from '@angular/core';
import { Observable, of, forkJoin } from 'rxjs';
import { delay,tap, map } from 'rxjs/operators';
import * as gc from 'src/app/global/const';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { JsonResult } from '../model/JsonResult';
import { SysObjectService, SysObject } from './sys-object.service';
import { SysRolepService, SysRolep } from './sys-rolep.service';
import { TableStyleService, TableStyle } from './table-style.service';
import { UUID } from 'angular2-uuid';
import { SysRole } from './sys-role.service';

/**
 * 2019年12月1日21:00:00
 * 本服务提供认证与授权的功能
 */
@Injectable({
  providedIn: 'root'
})
export class AuthService {
  isLoggedIn = false;
  redirectUrl: string;

  user:SysUser = null;

  urlPre = "/login";
  url = {
    'login':gc.BACKEND_SERVER + this.urlPre + '/in',
    'logout':gc.BACKEND_SERVER + this.urlPre + '/out',// 下面开始是授权相关
    
  }

  constructor(
    private router:Router,
    private http:HttpClient,
    private sysObjectService:SysObjectService,
    private sysRolePService:SysRolepService,
    private tsService:TableStyleService
  ) { }


  //#region 登录，成功后返回：{code: 1, status: "ok", msg: "登录成功", data: null}
  login(userid:string,password:string):Observable<JsonResult>{
    let user:SysUser = new SysUser();
    user.userid = userid;
    user.password = password;
    user.username = userid;
    
    // let headers = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' });
    // return this.http.post(this.url.login,{'username':userid,'password':password},{'headers':headers});
    // 下面的两个 key 名称不可修改，对应后端接口的属性名称
    return this.http.post<JsonResult>(this.url.login,{'username':userid,'password':password}).pipe(map(
      ( jr:JsonResult ) =>{
        if( jr.code !==1 ) return jr;

        console.log('登录成功后返回的数据是：');
        console.log(jr);
        this.user = jr.data.sysUser;
        console.log(this.user);
        
        this.isLoggedIn = true;
        console.log('已设置登录状态为true');
        // this.router.navigateByUrl('/layout');
        this.gotoIndex();
        return jr;
      }
    ));
  }
  //#endregion


  //#region 跳转到首页
  gotoIndex(){
    this.router.navigate(['/layout']);
  }
  //#endregion

  //#region 登出
  logout(): Observable<JsonResult>{
    return this.http.post<JsonResult>(this.url.logout,null).pipe(map(
      ( jr:JsonResult ) =>{
        // if( jr.code !==1 ){
        //   return JsonResult.getError('注销失败！');
        // }
        this.isLoggedIn = false;
        // console.log('注销成功返回的数据是：');
        // console.log(jr);
        this.router.navigate(['/login']);
        
        return jr;
      }
    ))
  }
  //#endregion


  /************************上面是认证，下面开始是授权*****************************************/
  sysRolepStyle:TableStyle[] = [];// 表 table_style 中 table_name=SysRolep 的记录集
  sysRoleps:SysRolep[] = [];// 以 sys_object 为基础构建指定角色的所有权限
  permEditCache:{ [key:string]:{ edit:boolean,data: SysRolep} } = {};

  private getAllObjects():Observable<JsonResult>{
    return this.sysObjectService.selectAll().pipe(map(
      ( jr:JsonResult ) =>{
        return jr;
      }
    ))
  }

  private getRolePermissions(roleIid:number):Observable<JsonResult>{
    return this.sysRolePService.selectByRoleIid(roleIid).pipe(map(
      ( jr:JsonResult ) =>{
        return jr;
      }
    ));
  }

  refresh(role:SysRole):Observable<JsonResult>{
    const style$ = this.getRolePermissionStyle$();
    const perms$ = this.getRolePermissions$(role);

    return forkJoin(style$,perms$).pipe(map(
      ( res:any[] ) =>{
        if( !res ) return JsonResult.getError('请求服务器数据时出现异常！');
        const jrStyle:JsonResult = res[0];
        const jrData:JsonResult = res[1];
        if( !jrStyle || jrStyle.code !==1 ) return JsonResult.getError('请求样式数据时出现异常！');
        if( !jrData || jrData.code !==1 ) return JsonResult.getError('请求权限数据时出现异常！');

        return JsonResult.ok();
      }
    ))
  }

  //#region 构建角色对于所有对象的权限，并保存到本服务的属性中
  private getRolePermissions$(record:SysRole):Observable<JsonResult>{
    const objs$ = this.getAllObjects();
    const roleP$ = this.getRolePermissions(record ? record.iid:0);
    return forkJoin(objs$ ,roleP$).pipe(map(
      ( res:any[] ) =>{
        if( !res ) return JsonResult.getError('融合角色权限失败！');
        const jrObjects:JsonResult = res[0];
        const jrRolePerms:JsonResult = res[1];

        if( !jrObjects ) return JsonResult.getError('获取系统对象列表失败！');
        if( !jrRolePerms ) return JsonResult.getError('获取角色权限列表失败！');

        const objects:SysObject[] = jrObjects.data;
        const perms:SysRolep[] = jrRolePerms.data;
        if( !objects ) return JsonResult.getError('获取系统对象列表失败！');
        if( !perms ) return JsonResult.getError('获取角色权限列表失败！');

        this.sysRoleps = [];
        objects.forEach(eleObj => {
          let tmp:SysRolep = new SysRolep();
          tmp.role_iid = record.iid;
          tmp.role_sid = record.roleid;
          tmp.object_iid = eleObj.iid;
          tmp.module_sid = eleObj.module_sid;
          tmp.object_sid = eleObj.object_sid;
          tmp.iid = 0;

          const objPerms:SysRolep[] = perms.filter( item => item.object_iid === eleObj.iid );
          if( objPerms.length>0 ){
            const perm:SysRolep = objPerms[0];
            if( perm ){
              tmp.iid = perm.iid;
              tmp.permission_audit = perm.permission_audit ? perm.permission_audit:null;
              tmp.permission_cancel = perm.permission_cancel ? perm.permission_cancel:null;
              tmp.permission_delete = perm.permission_delete ? perm.permission_delete:null;
              tmp.permission_export = perm.permission_export ? perm.permission_export:null;
              tmp.permission_money = perm.permission_money ? perm.permission_money:null;
              tmp.permission_new = perm.permission_new ? perm.permission_new:null;
              tmp.permission_print = perm.permission_print ? perm.permission_print:null;
              tmp.permission_update = perm.permission_update ? perm.permission_update:null;
              tmp.permission_view = perm.permission_view ? perm.permission_view:null;
            }
          }

          // 构建表格数据和缓存数据
          this.sysRoleps.push({...tmp});
          this.permEditCache[tmp.uuid] = { edit:false,data:{...tmp} };
        });
        
        this.sysRoleps = this.sysRoleps.filter( item => 1===1 );
        console.log('AuthService中请求来的权限数据、编辑缓存数据依次是：');
        console.log(this.sysRoleps);
        console.log(this.permEditCache);

        return JsonResult.ok();
      }
    ))
  }
  //#endregion


  //#region 请求获取权限表格样式，并保存到本服务的属性中
  private getRolePermissionStyle$():Observable<JsonResult>{
    const tableName:string = 'sys_rolep';
    return this.tsService.selectByTableName(tableName).pipe(map(
      ( jr:JsonResult ) =>{
        if( jr.code !==1 ) return jr;
        this.sysRolepStyle = jr.data;
        return jr;
      }
    ));
  }
  //#endregion

  //#region 保存编辑：保存远端成功后保存本地
  saveEdit(uuid:string,rowIndex:number):Observable<JsonResult>{
    let sysRolep:SysRolep = this.permEditCache[uuid].data;
    console.log('即将要保存的数据是：');
    console.log(sysRolep);
    return this.sysRolePService.saveOne(sysRolep).pipe(map(
      ( jr:JsonResult ) =>{
        if( jr.code !==1 ) return jr;

        // 远端保存成功则更新本地数据
        this.updateLocal8NewData(uuid,rowIndex,jr.data);
        return jr;
      }
    ))
  }
  //#endregion


  //#region 取消编辑
  cancelEdit(uuid:string,rowIndex:number){
    this.permEditCache[uuid].data = {...this.sysRoleps[rowIndex]};
    this.permEditCache[uuid].edit = false;
  }
  //#endregion


  //#region 将编辑缓存中的数据更新到属性数据中并且关闭编辑状态
  saveEditLocal(uuid:string,rowIndex:number){
    this.sysRoleps[rowIndex] = {...this.permEditCache[uuid].data};
    this.sysRoleps = this.sysRoleps.filter( item => 1===1 );
    this.permEditCache[uuid].edit = false;
  }
  //#endregion


  //#region 拿远端数据更新本地数据
  updateLocal8NewData(uuid:string,rowIndex:number,data:any){
    const newUuid:string = UUID.UUID();
    data.uuid = newUuid;
    this.sysRoleps[rowIndex] = {...data};
    this.sysRoleps = this.sysRoleps.filter( item => 1===1 );
    this.permEditCache[newUuid] = {edit:false,data:{...data}};
  }
  //#endregion
}



// Author：chanchaw
// Generator Version：1.0 - 2019年11月16日 16点46分
// This Model Created：Sat Nov 30 2019 08:29:19 GMT+0800 (中国标准时间)
export class SysUser{
  create_time:Date;
  iid:number;
  last_time:Date;
  non_expired:boolean;
  non_locked:boolean;
  non_password_expired:boolean;
  password:string;
  remark:string;
  status:number;
  userid:string;
  username:string;
}